import json
from hashlib import md5
from io import StringIO
from random import random

from django.http import HttpResponse
from django.http import Http404
from rest_framework import status
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from rest_framework.generics import ListCreateAPIView
from rest_framework.views import APIView

from api.ownserializers import CollectionSerializer, BrowseHistorySerializer
from common.models import TbCollection, TbStory
from common.models import TbBrowseHistory, TbStrategy
from user.captcha import Captcha
from common.models import TbUser


ALL_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'


def md5_ps(ps_str):
    """哈希码"""
    return md5(ps_str.encode('utf8')).hexdigest()


def gen_captcha_text(length=4):
    """生成指定长度的图片验证码文字"""
    code = StringIO()
    chars_len = len(ALL_CHARS)
    for _ in range(length):
        index = random.randrange(chars_len)
        code.write(ALL_CHARS[index])
    return code.getvalue()


def get_captcha(request):
    captcha_text = gen_captcha_text()
    image_bytes = Captcha.instance().generate(captcha_text)
    request.session['captcha'] = captcha_text.lower()
    return HttpResponse(image_bytes, content_type='image/png')


def register(request):
    """注册"""
    if request.method == 'GET':
        return HttpResponse(request)
    if request.method == 'POST':
        name = request.POST.get('name')
        username = request.POST.get('username')
        passwd = request.POST.get('passwd')
        tel = request.POST.get('tel')
        email = request.POST.get('email')
        # 验证参数是否填写完整
        if not all([name, username, passwd, tel, email]):
            error = {'msg': '请填写完整信息'}
            return HttpResponse(json.dumps(error), content_type='application/json; charset=utf-8')
        # 验证用户是否注册
        user = TbUser.objects.filter(username=username).first()
        if user:
            error = {'msg': '该用户名已注册'}
            return HttpResponse(json.dumps(error), content_type='application/json; charset=utf-8')
        # 验证手机号是否注册
        tel = TbUser.objects.filter(tel=tel).first()
        if tel:
            error = {'msg': '该手机已被注册'}
            return HttpResponse(json.dumps(error), content_type='application/json; charset=utf-8')
        # 创建用户
        res = TbUser.objects.create(name=name, username=username, passwd=md5_ps(passwd), tel=tel, email=email)
        return HttpResponse(json.dumps(res), content_type='application/json; charset=utf-8')


def login(request):
    """登录"""
    if request.method == 'POST':
        username = request.POST.get('username')
        passwd = request.POST.get('passwd')
        user = TbUser.objects.get(username=username)
        if not user:
            error = {'msg': '用户名或密码错误'}
            return HttpResponse(json.dumps(error), content_type='application/json; charset=utf-8')
        if user.passwd == md5_ps(passwd):
            request.session['username'] = user.username
            request.session['passwd'] = user.passwd
            hint = {'code': 200}
            return HttpResponse(json.dumps(hint), content_type='application/json; charset=utf-8')
        else:
            error = {'msg': '用户名或密码错误'}
            return HttpResponse(json.dumps(error), content_type='application/json; charset=utf-8')


def logout(request):
    """用户注销"""
    request.session.flush()
    hint = {'code': 200}
    return HttpResponse(json.dumps(hint), content_type='application/json; charset=utf-8')


class LKPageNumberPagination(PageNumberPagination):
    """继承rest_framework的分页器，重写参数，定义自己的分页器"""
    page_size = 5
    page_query_param = "page"
    page_size_query_param = "size"


class CollectionListView(ListCreateAPIView):
    """收藏视图类
        拥有：列表显示，创建收藏
    """
    queryset = TbCollection.objects.filter(flag=1).order_by('-create_time')
    serializer_class = CollectionSerializer

    def list(self, request, *args, **kwargs):
        """显示列表"""
        user_id = request.GET.get('user_id')
        queryset = self.get_queryset().filter(uid_id=user_id)
        # 使用分页器对结果分页，返回时方法用的和直接返回方法不一样
        pager = LKPageNumberPagination()
        paged_query_set = pager.paginate_queryset(
            queryset=queryset, request=request, view=self)

        return pager.get_paginated_response(
            CollectionSerializer(paged_query_set, many=True).data)

    def post(self, request, *args, **kwargs):
        """新增收藏"""
        article_id = request.POST.get('article_id')
        c_type = request.POST.get('type')
        try:
            if c_type:
                article = TbStory.objects.get(pk=article_id)
            else:
                article = TbStrategy.objects.get(pk=article_id)
        except Exception:
            raise Http404
        collection = TbCollection()
        serializer = CollectionSerializer(collection, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(status=status.HTTP_201_CREATED)
        return Response(status=status.HTTP_400_BAD_REQUEST)


class CollectionView(APIView):
    """取消收藏视图类"""

    def delete(self, request, pk, *args, **kwargs):
        try:
            collect = TbCollection.objects.get(pk=pk)
            collect.flag = 0
            collect.save()
            return Response(status=status.HTTP_204_NO_CONTENT)
        except TbCollection.DoesNotExist:
            raise Http404


class BrowseHistoryView(ListCreateAPIView):
    """浏览记录类视图
    拥有显示列表方法，创建新记录方法
    """
    queryset = TbBrowseHistory.objects.all().order_by('-watch_time')
    serializer_class = BrowseHistorySerializer

    def list(self, request, *args, **kwargs):
        try:
            user_id = request.GET.get('user_id')
            queryset = self.get_queryset().filter(uid_id=user_id)[:4]
            serializer = BrowseHistorySerializer(queryset, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except TbBrowseHistory.DoesNotExist:
            raise Http404

    def create(self, request, *args, **kwargs):
        article_id = request.POST.get('article_id')
        h_type = request.POST.get('type')
        try:
            if h_type:
                article = TbStory.objects.get(pk=article_id)
            else:
                article = TbStrategy.objects.get(pk=article_id)
        except Exception:
            raise Http404
        history = TbBrowseHistory()
        serializer = BrowseHistorySerializer(history, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(status=status.HTTP_201_CREATED)
        return Response(status=status.HTTP_400_BAD_REQUEST)
